home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9203.ZIP / 80X87.ASC < prev    next >
Text File  |  1992-01-24  |  5KB  |  155 lines

  1. _ASSEMBLY LANGUAGE PROGRAMMING FOR THE 80X87_
  2. by Nicholas Wilt
  3.  
  4. [LISTING ONE]
  5.  
  6. ; pow.asm: integer power function callable from Borland C++.
  7. ; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.
  8.  
  9. .MODEL  LARGE,C
  10.  
  11. .CODE
  12.  
  13. ; double intpow(double x, unsigned int y);
  14. ; Returns x^y.
  15.  
  16.     PUBLIC  intpow
  17.  
  18. intpow  PROC    X:QWORD,Y:WORD
  19.     fld1            ; Load 1 into the 80x87
  20.     mov cx,Y        ; Get y
  21.     fld X       ; Load x into the 80x87
  22.  
  23.     jcxz    Return      ; If y already zero, return
  24.  
  25. TestY:  test    cx,1        ; Is the LSB of y set?
  26.     jz  NextIteration   ; Jump if no
  27.     fmul    st(1),st    ; ret *= x
  28. NextIteration:
  29.     fmul    st,st(0)    ; Square x
  30.     shr cx,1        ; y >>= 1
  31.     jnz TestY       ; Continue if nonzero
  32. Return: fstp    st      ; Pop stack.  Return value is
  33.                 ; now in ST(0).
  34.     ret
  35. intpow  ENDP
  36.  
  37.     END
  38.  
  39.  
  40.  
  41. [LISTING TWO]
  42.  
  43. ; sumarray(), a Borland C++-callable function to sum the values
  44. ; in an array of floats.
  45.  
  46. ; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.
  47.  
  48. .MODEL  LARGE,C
  49.  
  50. .CODE
  51.  
  52. ; double sumarray(float *arr, int n);
  53. ;   Returns sum of the n elements in arr.
  54.  
  55.     PUBLIC  sumarray
  56.  
  57. sumarray    PROC    ARR:DWORD,N:WORD
  58.     les bx,ARR      ; ES:BX <- pointer to arr
  59.     mov cx,N        ; Get number of elements
  60.     fldz            ; Load zero
  61.     jcxz    LeaveSum    ; Leave if count is 0.
  62. DoSum:  fadd    dword ptr es:[bx] ; Add value in array to ST(0).
  63.     add bx,4        ; Point to next value in array.
  64.     loop    DoSum       ; Loop until done.
  65. LeaveSum:           ; Return value in ST(0).
  66.     ret
  67. sumarray    ENDP
  68.  
  69.     END
  70.  
  71.  
  72.  
  73. [LISTING THREE]
  74.  
  75. ; quad.asm: integer power function callable from Borland C++.
  76. ; Copyright (C) 1991 by Nicholas Wilt.  All rights reserved.
  77.  
  78. .MODEL  LARGE,C
  79.  
  80. .CODE
  81.  
  82. ; int solve_quadratic(double a, double b, double c, double *x1, double *x2);
  83. ; solve_quadratic takes the coefficients of a quadratic polynomial
  84. ; and finds the roots of that polynomial.  If there are two real
  85. ; roots, it writes them back to x1 and x2 and returns 1.  If the
  86. ; discriminant b^2-4*a*c is less than 0, the roots are not real
  87. ; and solve_quadratic returns 0.
  88. ; The quadratic formula is as follows:
  89. ;   (-b +/- sqrt(b*b-4*a*c)) / 2*a
  90.  
  91.     PUBLIC  solve_quadratic
  92.  
  93. solve_quadratic PROC    A:QWORD,B:QWORD,C:QWORD,X1:DWORD,X2:DWORD
  94.                 ; Comments show stack contents
  95.                 ; separated by | signs
  96.                 ; Stack top is at left
  97.     fld A       ; a     Here, ST(0) contains a.
  98.     fld B       ; b | a     Now ST(1) has a.  Etc.
  99.  
  100.     ; Negate b -- squaring it is sign-independent, and we need b
  101.     ; negated in all the other instances in the formula.
  102.     fchs
  103.  
  104.     fld C       ; c | b | a
  105.     fld st(1)       ; b | c | b | a
  106.     fmul    st,st(0)    ; b*b | c | b | a
  107.  
  108.     ; Just plain fxch has an implicit operand of ST(1).
  109.  
  110.     fxch            ; c | b*b | b | a
  111.     fadd    st,st(0)    ; 2*c | b*b | b | a
  112.     fadd    st,st(0)    ; 4*c | b*b | b | a
  113.     fmul    st,st(3)    ; 4*a*c | b*b | b | a
  114.     fsubp   st(1), st   ; b*b-4*a*c | b | a
  115.     ftst            ; Compare against 0
  116.  
  117.     ; We've computed b*b-4*a*c.  If negative, we return 0.
  118.     ; To do the comparison, we have to store the 80x87 status
  119.     ; word and use sahf to store it into the flags.  Once it's
  120.     ; in the flags, we can jump on above or equal (jae) to jump if the
  121.     ; number tested is greater than 0 after the FTST instruction above.
  122.     sub sp,2        ; Quick, allocate a local
  123.     mov bx,sp       ; Point BX at it
  124.     fstsw   ss:[bx]     ; Store the 80x87's status word there
  125.     mov ax,ss:[bx]  ; AX <- status word
  126.     add sp,2        ; Deallocate the local
  127.     sahf            ; Get SW into flags
  128.     jae ComputeResults  ; Jump if positive
  129.     fstp    st      ; This instruction clears the stack
  130.     fstp    st      ; we've got three values on the stack
  131.     fstp    st      ; to clear
  132.     xor ax,ax       ; Return 0 - no roots found.
  133.     jmp short LeaveQuadratic
  134. ComputeResults:
  135.     fsqrt           ; Find square root of discriminant
  136.     fxch    st(2)       ; a | b | sqrt(b*b-4*a*c)
  137.     fadd    st,st(0)    ; 2*a | b | sqrt(b*b-4*a*c)
  138.     fld st(1)       ; b | 2*a | b | sqrt(b*b-4*a*c)
  139.     fadd    st,st(3)    ; b+sqrt(b*b-4*a*c) | 2*a | b | sq..
  140.     fdiv    st,st(1)    ; x1 | 2*a | b | sqrt(b*b-4*a*c)
  141.     les bx,X1       ;
  142.     fstp    qword ptr es:[bx] ; 2*a | b | sqrt(b*b-4*a*c)
  143.     fxch            ; b | 2*a | sqrt(b*b-4*a*c)
  144.     fsubrp  st(2),st    ; 2*a | -b - sqrt(b*b-4*a*c)
  145.     fdiv            ; x2
  146.     les bx,X2       ; Store x2
  147.     fstp    qword ptr es:[bx]
  148.     mov ax,1        ; Return 1
  149. LeaveQuadratic:
  150.     ret         ; Return
  151. solve_quadratic ENDP
  152.  
  153.     END
  154.  
  155.